package cz.muni.fi.pa165.restclient;

import cz.muni.fi.pa165.api.dto.ForestDTO;
import java.io.BufferedReader;
import java.io.IOException;
import java.net.URI;
import java.util.ResourceBundle;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestTemplate;

/**
 * ForestHandler class represents a forest part of menu
 *
 * @author Michal Becak
 */
public class ForestHandler {

    private BufferedReader reader;
    private RestTemplate rt = new RestTemplate();
    private ResourceBundle rb = ResourceBundle.getBundle("cz.muni.fi.pa165.restclient.resources.urlPaths");

    public ForestHandler(BufferedReader reader) {
        this.reader = reader;
    }

    public void forestMenu() throws IOException {
        for (;;) {
            System.out.println("");
            System.out.println("Forest menu");
            System.out.println("1. Create forest");
            System.out.println("2. Update forest");
            System.out.println("3. Delete forest");
            System.out.println("4. Get all forests");
            System.out.println("5. Get forest by name");
            System.out.println("Make your selection {1, 2, 3, 4}, m for main menu, x for exit");
            String result = reader.readLine();
            switch (result) {
                case "1":
                    createForest();
                    break;
                case "2":
                    updateForest();
                    break;
                case "3":
                    deleteForest();
                    break;
                case "4":
                    getAllForests();
                    break;
                case "5":
                    getForestByName();
                    break;
                case "m":
                    return;
                case "x":
                    System.exit(0);
                default:
                    System.out.println("Invalid choice, try again!");
            }
        }
    }

    public void createForest() throws IOException {
        for (;;) {
            System.out.println("");
            System.out.println("Create a new forest");
            System.out.println("Enter the name: (required)");
            String name = reader.readLine();
            if (name.isEmpty()) {
                System.out.println("Name has not been filled, try again.");
                continue;
            }
            try {
                ForestDTO forestCheck = rt.getForObject(rb.getString("serverPath") + rb.getString("getForestByName"), ForestDTO.class, name);
                if (forestCheck != null) {
                    System.out.println("Forest with given name already exists.");
                    continue;
                }

                System.out.println("Enter the description: (optional)");
                String description = reader.readLine();

                ForestDTO forestDTO = new ForestDTO();
                forestDTO.setName(name);
                forestDTO.setLocationInfo(description);

                URI uri = rt.postForLocation(rb.getString("serverPath") + rb.getString("createForest"), forestDTO);
            } catch (HttpServerErrorException ex) {
                System.out.println("Error has occured, returning back to menu.");
                return;
            }

            System.out.println("Choose your action: c - continue, r - return to forest menu, x - exit");
            for (boolean cont = true; cont;) {
                String result = reader.readLine();
                switch (result) {
                    case "c":
                        cont = false;
                        break;
                    case "r":
                        return;
                    case "x":
                        System.exit(0);
                    default:
                        System.out.println("Incorrect choice, try again!");
                        System.out.println("Choose your action: c - continue, r - return to forest menu, x - exit");
                }
            }
        }
    }

    public void updateForest() throws IOException {
        for (;;) {
            System.out.println("");
            System.out.println("Update forest");
            try {
                printForests();
            } catch (HttpServerErrorException ex) {
                System.out.println("Error has occured, returning back to menu.");
                return;
            }
            System.out.println("Choose forest's id number");
            Long id = null;
            try {
                id = Long.valueOf(reader.readLine());
            } catch (NumberFormatException ex) {
                System.out.println("ID must be correctly filled number.");
                continue;
            }
            ForestDTO forest = null;
            try {
                forest = getForest(id);
            } catch (HttpServerErrorException ex) {
                System.out.println("Error has occured, returning back to menu");
                return;
            }

            if (forest == null) {
                System.out.println("Forest with given id does not exist");
                continue;
            }

            String name = null;
            do {
                System.out.println("Enter new name (old name: " + forest.getName() + ") (required)");
            } while ((name = reader.readLine()).isEmpty());

            forest.setName(name);
            System.out.println("Enter new location info (old info: " + forest.getLocationInfo() + ") (optional)");
            forest.setLocationInfo(reader.readLine());

            try {
                URI uri = rt.postForLocation(rb.getString("serverPath") + rb.getString("updateForest"), forest);
            } catch (HttpServerErrorException ex) {
                System.out.println("Error has occured, returning back to menu.");
                return;
            }
            System.out.println("Choose your action: c - continue, r - return to forest menu, x - exit");
            for (boolean cont = true; cont;) {
                String result = reader.readLine();
                switch (result) {
                    case "c":
                        cont = false;
                        break;
                    case "r":
                        return;
                    case "x":
                        System.exit(0);
                    default:
                        System.out.println("Incorrect choice, try again!");
                        System.out.println("Choose your action: c - continue, r - return to forest menu, x - exit");
                }
            }
        }
    }

    public void deleteForest() throws IOException {
        for (;;) {
            System.out.println("");
            System.out.println("Delete forest");
            try {
                printForests();
            } catch (HttpServerErrorException ex) {
                System.out.println("Error has occured, returning back to menu.");
                return;
            }
            System.out.println("Choose forest's id number");

            Long id = null;
            try {
                id = Long.valueOf(reader.readLine());
            } catch (NumberFormatException ex) {
                System.out.println("ID must be correctly filled number.");
                continue;
            }

            System.out.println("Are you sure? All forest visits with given forest will be removed! (y/n)");
            String res = reader.readLine();
            switch (res) {
                case "y":
                    break;
                case "n":
                    return;
                default:
                    System.out.println("Incorrect choice, returning back to forest menu");
                    return;
            }

            try {
                ForestDTO forest = getForest(id);
                if (forest == null) {
                    System.out.println("Forest with given id does not exist.");
                    continue;
                }
                URI uri = rt.postForLocation(rb.getString("serverPath") + rb.getString("removeForest"), forest);
            } catch (HttpServerErrorException ex) {
                System.out.println("Error has occured, returning back to menu.");
                return;
            }

            System.out.println("Choose your action: c - continue, r - return to forest menu, x - exit");
            for (boolean cont = true; cont;) {
                String result = reader.readLine();
                switch (result) {
                    case "c":
                        cont = false;
                        break;
                    case "r":
                        return;
                    case "x":
                        System.exit(0);
                    default:
                        System.out.println("Incorrect choice, try again!");
                        System.out.println("Choose your action: c - continue, r - return to forest menu, x - exit");
                }
            }
        }
    }

    public void getAllForests() throws IOException {
        System.out.println("");
        System.out.println("List of all forests:");
        try {
            printForests();
        } catch (HttpServerErrorException ex) {
            System.out.println("Error has occured, returning back to menu.");
            return;
        }
        System.out.println("Choose your action: r - return to forest menu, x - exit");
        for (;;) {
            String result = reader.readLine();
            switch (result) {
                case "r":
                    return;
                case "x":
                    System.exit(0);
                default:
                    System.out.println("Incorrect choice, try again!");
                    System.out.println("Choose your action: r - return to forest menu, x - exit");
            }
        }
    }

    public void getForestByName() throws IOException {
        for (;;) {
            System.out.println("");
            System.out.println("Enter forest name:");
            String name = reader.readLine();
            if (name.isEmpty()) {
                continue;
            }
            ForestDTO forestDTO = null;
            try {
                forestDTO = rt.getForObject(rb.getString("serverPath") + rb.getString("getForestByName"), ForestDTO.class, name);
            } catch (HttpServerErrorException ex) {
                System.out.println("Error has occured, returning back to menu.");
                return;
            }
            if (forestDTO == null) {
                System.out.println("Forest with given name does not exist.");
            } else {
                System.out.println("Returned forest:");
                System.out.printf("Id: %d, name: %s, info: %s%n", forestDTO.getId(), forestDTO.getName(), forestDTO.getLocationInfo());

                System.out.println("Choose your action: c - continue, r - return to forest menu, x - exit");
                for (boolean cont = true; cont;) {
                    String result = reader.readLine();
                    switch (result) {
                        case "c":
                            cont = false;
                            break;
                        case "r":
                            return;
                        case "x":
                            System.exit(0);
                        default:
                            System.out.println("Incorrect choice, try again!");
                            System.out.println("Choose your action: c - continue, r - return to forest menu, x - exit");
                    }
                }
            }
        }
    }

    public void printForests() {
        ForestDTO[] f = rt.getForObject(rb.getString("serverPath") + rb.getString("getAllForests"), ForestDTO[].class);
        for (ForestDTO forestDTO : f) {
            System.out.printf("Id: %d, name: %s, info: %s%n", forestDTO.getId(), forestDTO.getName(), forestDTO.getLocationInfo());
        }
    }

    public ForestDTO getForest(Long id) {
        return rt.getForObject(rb.getString("serverPath") + rb.getString("getForest"), ForestDTO.class, id.toString());
    }
}
